#include <DoublyNode.hh>
#include "DoublyNodeTest.hh"

ResultOf DoublyNodeTest::testLink(Node* N, Node* N2)
{
	ResultOf Result;
	Result = N->linkLeft(N2);
	checkErrorWR(Result, "Fail N->linkLeft.");
	
	if (N->tellLeft() != N2 || N->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != NULL || N2->tellRight() != N)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	Result = N->unlink();
	
	if (N->tellLeft() != NULL || N->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != NULL || N2->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	Result = N->linkLeft(N2);
	checkErrorWR(Result, "Fail N->linkLeft.");
	
	if (N->tellLeft() != N2 || N->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != NULL || N2->tellRight() != N)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	Result = N2->unlink();
	
	if (N->tellLeft() != NULL || N->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != NULL || N2->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	return RETURN_OK;
}

ResultOf DoublyNodeTest::testLink2(Node* N, Node* N2)
{
	ResultOf Result;
	Result = N->linkRight(N2);
	checkErrorWR(Result, "Fail N->linkLeft.");
	
	if (N->tellLeft() != NULL || N->tellRight() != N2)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != N || N2->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	Result = N->unlink();
	
	if (N->tellLeft() != NULL || N->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != NULL || N2->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	Result = N->linkRight(N2);
	checkErrorWR(Result, "Fail N->linkLeft.");
	
	if (N->tellLeft() != NULL || N->tellRight() != N2)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != N || N2->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	Result = N2->unlink();
	
	if (N->tellLeft() != NULL || N->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != NULL || N2->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	return RETURN_OK;
}

ResultOf DoublyNodeTest::testLink3(Node* N, Node* N2)
{
	ResultOf Result;
	Result = N->linkLeft(N2);
	checkErrorWR(Result, "Fail N->linkLeft.");
	
	if (N->tellLeft() != N2 || N->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != NULL || N2->tellRight() != N)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	Result = N->linkLeft(N2);
	checkErrorWR(Result, "Fail N->linkLeft.");
	
	if (N->tellLeft() != N2 || N->tellRight() != NULL)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N->tellLeft(), "Left of N.");
		notifyError(N->tellRight(), "Right of N.");
		return RETURN_OK;
	}
	
	if (N2->tellLeft() != NULL || N2->tellRight() != N)
	{
		notifyError(N, "N.");
		notifyError(N2, "N2.");
		notifyError(N2->tellLeft(), "Left of N2.");
		notifyError(N2->tellRight(), "Right of N2.");
		return RETURN_OK;
	}
	
	return RETURN_OK;
}

ResultOf testDoublyNode()
{
	ResultOf Result;
	DoublyNode Node1;
	DoublyNode Node2;
	DoublyNode Node3;
	DoublyNodeTest Test;
	
	Result = Test.testLink(&Node1, &Node2);
	checkErrorWR(Result, "Fail Test.testBasicCase.");
	
	Result = Test.testLink2(&Node1, &Node2);
	checkErrorWR(Result, "Fail Test.testBasicCase2.");
	
	fprintf(stderr, "DoublyNode: Test success.\n");
	return RETURN_OK;
}
